package com.shanxia.codec.cmd;

import com.shanxia.codec.ProtocolDataBase;
import com.shanxia.codec.enums.DecodeEnum;
import lombok.Data;

import java.math.BigDecimal;
import java.util.Arrays;

import static com.shanxia.codec.CodeConstant.HUNDRED;
import static com.shanxia.codec.CodeConstant.PERCENT;
import static com.shanxia.codec.Decoder.*;

/**
 * S -> C
 * 服务器应答充电桩上报充电信息报文
 * TODO demo字节数少，未通过验证
 */
@Data
public class Cmd201 extends ProtocolDataBase {

    public static final int MIN_SIZE = 66;

    private int v1;
    private int v2;
    private int chargingPortNum;                        // 充电口号
    private String chargingCardNum;                     // 充电卡号
    private int indexNum;                               // 内部索引号
    private int effectiveSign;                          // 7、8、9 字段有效标志(充电优惠前金额、充电折扣金额、充电实扣金额)
    private double fullChargingAmount;                  // 充电优惠前金额
    private double discountAmount;                      // 充电折扣金额
    private double paidAmount;                          // 充电实扣金额
    private double balance;                             // 用户剩余金额
    private double paidChargingAmount;                  // 充电实扣电费
    private double paidServiceAmount;                   // 充电实扣服务费

    public Cmd201(){
        super.setCmd(201);
    }

    public static Cmd201 decodeFromBase(ProtocolDataBase protocolDataBase) {
        Cmd201 cmd = new Cmd201();
        cmd.copyDataFrom(protocolDataBase);
        byte[] dataField = protocolDataBase.getDataField();
        //数据域长度
        if (dataField.length < MIN_SIZE) {
            cmd.setResult(DecodeEnum.InvalidData);
            return cmd;
        }
        int offset = 0;
        cmd.v1 = getUint16(dataField, offset);
        offset += 2;
        cmd.v2 = getUint16(dataField, offset);
        offset += 2;
        // 1字节充电口号
        cmd.chargingPortNum = getUint8(dataField[offset++]);
        // 32字节充电卡号
        cmd.chargingCardNum = byteToAscii(Arrays.copyOfRange(dataField, offset, offset + 32), true);
        offset += 32;
        // 4字节内部索引号
        cmd.indexNum = getInt32(dataField, offset);
        offset += 4;
        // 1字节7、8、9 字段有效标志(充电优惠前金额,充电折扣金额,充电实扣金额)
        cmd.effectiveSign = getUint8(dataField[offset++]);
        // 4字节充电优惠前金额
        cmd.fullChargingAmount = new BigDecimal(getInt32(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 4;
        // 4字节充电折扣金额
        cmd.discountAmount = new BigDecimal(getInt32(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 4;
        // 4字节充电实扣金额
        cmd.paidAmount = new BigDecimal(getInt32(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 4;
        // 4字节用户剩余金额
        cmd.balance = new BigDecimal(getInt32(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 4;
        // 4字节充电实扣电费
        cmd.paidChargingAmount = new BigDecimal(getInt32(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 4;
        // 4字节充电实扣服务费
        cmd.paidServiceAmount = new BigDecimal(getInt32(dataField, offset)).multiply(PERCENT).doubleValue();
        return cmd;
    }

    @Override
    public byte[] getDataField() {
        byte[] data = new byte[MIN_SIZE];
        getBytesAsUint16(data, 0, this.v1);
        getBytesAsUint16(data, 2, this.v2);
        // 1字节充电口号
        data[4] = (byte) this.chargingPortNum;
        // 32字节充电卡号
        getBytesAsUint16(data, 5, 32);
        // 4字节内部索引号
        intToBytesLittle(data, 37, this.indexNum);
        // 1字节字段有效标志
        data[41] = (byte) this.effectiveSign;
        // 4字节充电优惠前金额
        intToBytesLittle(data, 42, new BigDecimal(String.valueOf(this.fullChargingAmount)).multiply(HUNDRED).intValue());
        // 4字节充电折扣金额
        intToBytesLittle(data, 46, new BigDecimal(String.valueOf(this.discountAmount)).multiply(HUNDRED).intValue());
        // 4字节充电实扣金额
        intToBytesLittle(data, 50, new BigDecimal(String.valueOf(this.paidAmount)).multiply(HUNDRED).intValue());
        // 4字节用户剩余金额
        intToBytesLittle(data, 54, new BigDecimal(String.valueOf(this.balance)).multiply(HUNDRED).intValue());
        // 4字节充电实扣电费
        intToBytesLittle(data, 54, new BigDecimal(String.valueOf(this.paidChargingAmount)).multiply(HUNDRED).intValue());
        // 4字节充电实扣服务费
        intToBytesLittle(data, 58, new BigDecimal(String.valueOf(this.paidServiceAmount)).multiply(HUNDRED).intValue());
        return data;
    }
}
